//
//  OperationLog.m
//  Guazi
//
//  Created by koolearn on 11-6-18.
//  Copyright 2011年 __MyCompanyName__. All rights reserved.
//

#import <sqlite3.h>
#import "OperationLog.h"
#import "DBConnection.h"
#import "GuaziAppDelegate.h"


@implementation OperationLog

@synthesize logId;
@synthesize userId;
@synthesize module;
@synthesize operation;
@synthesize refId;
@synthesize createAt;
@synthesize params;
@synthesize status;
@synthesize uploadTime;
@synthesize uploadCount;


#pragma mark - 生命周期方法


- (id) initWithStatement:(Statement*)stmt
{
    self = [super init];
    if ( self ) {
        self.logId = [stmt getInt32:0];
        self.userId = [stmt getInt64:1];
        self.module = [stmt getString:2];
        self.operation = [stmt getString:3];
        self.refId = [stmt getString:4];
        self.createAt = [stmt getInt64:5];
        self.params = [stmt getString:6];
        self.status = [stmt getInt32:7];
        self.uploadTime = [stmt getInt64:8];
        self.uploadCount = [stmt getInt32:9];
    }
    return self;
}


- (id) initWithModule:(NSString*)m operation:(NSString*)op refId:(NSString*)r params:(NSString*)p
{
    self = [super init];
    if ( self ) {
        self.logId = 0;
        self.module = m;
        self.operation = op;
        self.userId = [GuaziAppDelegate getAppDelegate].user.userId;
        self.refId = r;
        self.params = p;
        self.status = kOperationLogStatusLocal;
    }
    return self;
}


- (void) dealloc
{
    [module release];
    [operation release];
    [refId release];
    [params release];
    [super dealloc];
}


- (NSString*) toString
{
    NSString* s = [NSString stringWithFormat:@"{id:\"%lld\", module:\"%@\", operation:\"%@\", params:%@,createdAt:\"%lld\"}", self.logId, self.module, self.operation, self.params, self.createAt];
    return s;
}


#pragma mark - 数据库操作方法

- (void) insert
{
    sqlite3* db = [DBConnection getDatabase];
    char* sql = "insert into operation_log (module, operation, ref_id, created_at, params, owner_user_id, status, upload_count) values (?,?,?,?,?,?,0,0)";
    
    Statement* stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindString:self.module forIndex:1];
    [stmt bindString:self.operation forIndex:2];
    [stmt bindString:self.refId forIndex:3];
    
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSince1970];
    [stmt bindInt64:(long long)timeInterval forIndex:4];

    [stmt bindString:self.params forIndex:5];
    [stmt bindInt64:self.userId forIndex:6];
    
    if ([stmt step]!=SQLITE_DONE) {
        [stmt release];
		NSAssert2( 0, @"Fail to execute sql: %s (%s)", sql, sqlite3_errmsg(db) );
		return;
    }
    else {
        [stmt release];
    }
}


+ (NSArray*) select:(OperationLogFilter*)filter
{
    NSMutableString* s = [NSMutableString string];
    
    if ( filter.module != nil ) {
        [s appendFormat:@" and module = '%@'", filter.module];
    }
    
    if ( filter.operation!=nil ) {
        [s appendFormat:@" and operation = '%@'", filter.operation];
    }
    
    if ( filter.refId != nil ) {
        [s appendFormat:@" and ref_id = '%@'", filter.refId];
    }
    
    if ( filter.createAtBegin > 0 ) {
        [s appendFormat:@" and created_at >= %d", (NSInteger)filter.createAtBegin];
    }
    
    if ( filter.createAtEnd > 0 ) {
        [s appendFormat:@" and created_at <= %d", (NSInteger) filter.createAtEnd];
    }
    
    if ( filter.userId > 0 ) {
        [s appendFormat:@" and owner_user_id = %lld", filter.userId];
    }
    
    if ( filter.status != -1 ) {
        [s appendFormat:@" and status = %d", filter.status];
    }
    
    if ( filter.lowerUploadCount != -1 ) {
        [s appendFormat:@" and upload_count >= %d", filter.lowerUploadCount];
    }
    
    if ( filter.upperUploadCount != -1 ) {
        [s appendFormat:@" and upload_count <= %d", filter.upperUploadCount];
    }
    
    
    NSMutableString* sql = [NSMutableString stringWithString:@"select id, owner_user_id, module, operation, ref_id, created_at, params, status, upload_time, upload_count from operation_log"];
    if ( [s length] > 0 ) {
        [sql appendString:[s substringFromIndex:5]];
    }
    
    [sql appendString:@" order by created_at"];
    
    if ( filter.pageNo >= 0 && filter.rowsPerPage > 0 ) {
        [sql appendFormat:@" limit %d offset %d", filter.pageNo*filter.rowsPerPage, filter.rowsPerPage];
    }
    
    sqlite3* db = [DBConnection getDatabase];
    Statement* stmt = [[Statement alloc] initWithDB:db sql:(char*)[sql UTF8String]];
    
    NSMutableArray* array = [NSMutableArray array];
    while ( [stmt step]==SQLITE_ROW ) {
        OperationLog* log = [[OperationLog alloc] initWithStatement:stmt];
        [array addObject:log];
        [log release];
    }
    
    [stmt release];
    return array;
}


+ (NSArray*) selectForUpload:(NSInteger)maxUploadCount offset:(NSInteger)offset limit:(NSInteger)limit
{
    sqlite3* db = [DBConnection getDatabase];
    
    NSString* sql = [NSString stringWithFormat:@"select * from (select id, owner_user_id, module, operation, ref_id, created_at, params, status, upload_time, upload_count from operation_log where owner_user_id = ? and (status = %d or (status = %d and upload_count < ?)) order by created_at) limit ? offset ?", kOperationLogStatusLocal, kOperationLogStatusFail];
    Statement* stmt = [[Statement alloc] initWithDB:db sql:(char*)[sql UTF8String]];
    [stmt bindInt64:[GuaziAppDelegate getAppDelegate].user.userId forIndex:1];
    [stmt bindInt32:3 forIndex:2];
    [stmt bindInt32:limit forIndex:3];
    [stmt bindInt32:offset forIndex:4];
    
    NSMutableArray* array = [NSMutableArray array];
    while ( [stmt step]==SQLITE_ROW ) {
        OperationLog* log = [[OperationLog alloc] initWithStatement:stmt];
        [array addObject:log];
        [log release];
    }
    
    [stmt release];
    return array;
}


+ (void) updateResult:(BOOL)result logId:(long long)logId
{
    sqlite3* db = [DBConnection getDatabase];
    char* sql = "update operation_log set status = ?, upload_time = ?, upload_count = upload_count + 1 where id = ?";
    
    NSTimeInterval t = [[NSDate date] timeIntervalSince1970];
    Statement* stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindInt32:(result?kOperationLogStatusSuccess:kOperationLogStatusFail) forIndex:1];
    [stmt bindInt64:(long long)t forIndex:2];
    [stmt bindInt64:logId forIndex:3];
    
    if ([stmt step]!=SQLITE_DONE) {
        [stmt release];
		NSAssert2( 0, @"Fail to execute sql: %s (%s)", sql, sqlite3_errmsg(db) );
		return;
    }
    else {
        [stmt release];
    }
}

@end
